from typing import Any, Dict, Optional, Union, List

from sqlalchemy.orm import Session

from app.core.security import get_password_hash, verify_password
from app.crud.base import CRUDBase
from app.models.user import SysUsers
from app.schemas.user import UserCreate, UserUpdate


class CRUDUser(CRUDBase[SysUsers, UserCreate, UserUpdate]):
    """
    用户CRUD操作
    """
    def get_by_username(self, db: Session, *, username: str) -> Optional[SysUsers]:
        """
        根据用户名获取用户
        """
        return db.query(SysUsers).filter(SysUsers.user_name == username).first()

    def create(self, db: Session, *, obj_in: UserCreate, created_by: str = None) -> SysUsers:
        """
        创建用户，密码自动加密
        """
        db_obj = SysUsers(
            user_name=obj_in.user_name,
            real_name=obj_in.real_name,
            email=obj_in.email,
            status=obj_in.status,
            role=obj_in.role,
            password=get_password_hash(obj_in.password),
            create_by=created_by
        )
        db.add(db_obj)
        db.commit()
        db.refresh(db_obj)
        return db_obj

    def update(
        self, db: Session, *, db_obj: SysUsers, obj_in: Union[UserUpdate, Dict[str, Any]], updated_by: str = None
    ) -> SysUsers:
        """
        更新用户信息，如果包含密码则自动加密
        """
        if isinstance(obj_in, dict):
            update_data = obj_in
        else:
            update_data = obj_in.dict(exclude_unset=True)
            
        # 版本控制检查
        if hasattr(obj_in, "version") and obj_in.version != db_obj.version:
            raise ValueError("数据已被修改，请刷新后再试")
        
        # 更新版本号
        db_obj.version += 1
            
        if "password" in update_data and update_data["password"]:
            hashed_password = get_password_hash(update_data["password"])
            del update_data["password"]
            update_data["password"] = hashed_password
        
        if updated_by:
            update_data["update_by"] = updated_by
            
        for field in update_data:
            if field != "version":  # 排除版本字段，因为我们已经手动增加了
                setattr(db_obj, field, update_data[field])
            
        db.add(db_obj)
        db.commit()
        db.refresh(db_obj)
        return db_obj
        
    def remove(self, db: Session, *, id: int) -> SysUsers:
        """
        逻辑删除用户 (设置状态为禁用)
        """
        obj = db.query(SysUsers).get(id)
        obj.status = 0  # 设置为禁用状态
        db.add(obj)
        db.commit()
        db.refresh(obj)
        return obj
        
    def authenticate(self, db: Session, *, username: str, password: str) -> Optional[SysUsers]:
        """
        验证用户
        """
        user = self.get_by_username(db, username=username)
        if not user:
            return None
        if not verify_password(password, user.password):
            return None
        return user

    def is_active(self, user: SysUsers) -> bool:
        """
        检查用户是否激活
        """
        return user.status == 1  # 1表示启用
        
    def is_admin(self, user: SysUsers) -> bool:
        """
        检查用户是否为管理员
        """
        return user.role == 1  # 1表示管理员

    def get_multi(
        self, db: Session, *, skip: int = 0, limit: int = 100, 
        user_name: Optional[str] = None, real_name: Optional[str] = None,
        email: Optional[str] = None, status: Optional[int] = None,
        role: Optional[int] = None
    ) -> List[SysUsers]:
        """
        获取多条记录，支持搜索条件
        """
        query = self._filter_query(
            db,
            user_name=user_name,
            real_name=real_name,
            email=email,
            status=status,
            role=role
        )
        return query.offset(skip).limit(limit).all()
        
    def _filter_query(
        self,
        db: Session,
        *,
        user_name: Optional[str] = None,
        real_name: Optional[str] = None,
        email: Optional[str] = None,
        status: Optional[int] = None,
        role: Optional[int] = None
    ):
        query = db.query(SysUsers)
        if user_name:
            query = query.filter(SysUsers.user_name.like(f"%{user_name}%"))
        if real_name:
            query = query.filter(SysUsers.real_name.like(f"%{real_name}%"))
        if email:
            query = query.filter(SysUsers.email.like(f"%{email}%"))
        if status is not None:
            query = query.filter(SysUsers.status == status)
        if role is not None:
            query = query.filter(SysUsers.role == role)
        return query

    def count(
        self,
        db: Session,
        *,
        user_name: Optional[str] = None,
        real_name: Optional[str] = None,
        email: Optional[str] = None,
        status: Optional[int] = None,
        role: Optional[int] = None
    ) -> int:
        query = self._filter_query(
            db,
            user_name=user_name,
            real_name=real_name,
            email=email,
            status=status,
            role=role
        )
        return query.count()


# 创建实例以便导入
user = CRUDUser(SysUsers)